package com.lx.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Test;

/**
 * Stream操作三个步骤：
 * 一.创建流
 * 二.中间操作
 * 三.终止流
 * @author liuxing
 *
 */
public class StreamDriver {

	List<Employee> elist = Arrays.asList(new Employee("aaa", 45, 8888.88), new Employee("aaa", 45, 8888.88),
			new Employee("aaa", 45, 8888.88), new Employee("bbb", 32, 6666.66), new Employee("ccc", 47, 7777.77),
			new Employee("ddd", 89, 5555.55), new Employee("eee", 12, 9999.99));

	/**
	 * 创建流的四种方式
	 */
	@SuppressWarnings("unused")
	@Test
	public void createStream() {
		//1.通过Collection集合提供的stream()方法获取流
		List<String> sList = new ArrayList<>();
		Stream<String> stream = sList.stream();
		//2.通过Arrays.stream(数组)获取
		String[] array = new String[10];
		Stream<String> stream2 = Arrays.stream(array);
		//3.通过Stream.of()方法获取
		Stream<String> stream3 = Stream.of("Hello");
		//4.通过函数产生流
		//1).迭代:生成20，21，22，23 .... 
		Stream<Integer> stream4 = Stream.iterate(20, x -> x + 1);
		//2).生成：一直生成100以内的随机数
		Stream<Integer> stream5 = Stream.generate(() -> new Random().nextInt(100));
	}

	/**
	 * 中间操作
	 */
	/**
	 filter(Predicate p) 	接收 Lambda , 从流中排除某些元素
	 distinct()	筛选,通过流所生成元素的 hashCode() 和 equals() 去 除重复元素
	 limit(long maxSize)	截断流,使其元素不超过给定数量
	 skip(long n)	跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素 不足 n 个,则返回一个空流。与 limit(n) 互补
	
	 map(Function f) 	接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。
	 flatMap(Function f)	接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
	 sorted(Comparator comp)	产生一个新流,其中按比较器顺序排序
	 */
	@Test
	public void filter() {
		System.out.println("--------查找年龄大于40的人-----");
		System.out.println();
		Stream<Employee> filter = elist.stream().filter(x -> x.getAge() > 40);
		filter.forEach(System.out::println);

		System.out.println("-----去重，去掉信息相同的人---------");
		Stream<Employee> distinct = elist.stream().distinct();
		distinct.forEach(System.out::println);

		System.out.println("------跳过2个元素后取2个元素-----------");
		elist.stream().skip(2).limit(2).forEach(System.out::println);

		System.out.println("------打印每个人的姓名--------------");
		elist.stream().map((x) -> x.getName()).forEach(System.out::println);

		System.out.println("-----打印每个人的姓名每个字符为一行-----------");
		System.out.println("--------1.使用map");

		//获取到的是一个流的流
		Stream<Stream<Character>> map = elist.stream().map(x -> getCharStram(x.getName()));
		map.forEach(x -> x.forEach(System.out::println));

		//获取到的是一个合并后的流
		System.out.println("--------2.使用flatMap");
		Stream<Character> flatMap = elist.stream().flatMap(x -> getCharStram(x.getName()));
		flatMap.forEach(System.out::println);

		System.out.println("------按年龄排序------");
		Stream<Employee> sorted = elist.stream().sorted((x, y) -> x.getAge().compareTo(y.getAge()));
		sorted.forEach(System.out::println);
	}

	/**
	 * 通过一个字符串获取Stream<Character>
	 * @param str
	 * @return
	 */
	private Stream<Character> getCharStram(String str) {
		List<Character> cList = new ArrayList<>();
		for (char c : str.toCharArray()) {
			cList.add(c);
		}
		return cList.stream();
	}

	/**
	 * 终止操作
	 * @param args
	 */
	@Test
	public void finalOp() {
		//检查是否所有的人年龄大于30
		boolean allMatch = elist.stream().allMatch(x -> x.getAge() > 30);
		System.out.println("是否所有的人年龄大于30 ： " + allMatch);
		boolean anyMatch = elist.stream().anyMatch(x -> x.getAge() > 30);
		System.out.println("查看是否有年龄大于30的：" + anyMatch);
		Optional<Employee> first = elist.stream().findFirst();
		Employee employee = first.get();
		System.out.println("第一个元素是：" + employee);
		Optional<Employee> max = elist.stream().max((x, y) -> x.getSalary().compareTo(y.getSalary()));
		System.out.println("最高工资是：" + max.get().getSalary());

		Optional<Employee> reduce = elist.stream().reduce((x, y) -> {
			double s = x.getSalary() + y.getSalary();
			x.setSalary(s);
			return x;
		});
		System.out.println("工资总和为："+reduce.get().getSalary());
	}
	
	/**
	 * 收集
	 */
	@Test
	public void collect(){
		//找出集合中年龄大于30岁的，放入到一个新的集合
		List<Employee> elist2 = elist.stream().filter(x->x.getAge()>30).collect(Collectors.toList());
		//统计工资大于7000的人数
		Long c = elist.stream().filter(x->x.getSalary()>7000).collect(Collectors.counting());
		System.out.println("年龄大于7000的人数为："+c);
		
		Double avgAge = elist.stream().collect(Collectors.averagingInt(x->x.getAge()));
		System.out.println("平均年龄是："+avgAge);
		
		String collect = elist.stream().map(x->x.getName()).collect(Collectors.joining(","));
		System.out.println("所有的姓名是:"+collect);
		
	}

	
	public static void main(String[] args) {
		List<Object> l = new ArrayList<>();
		List<Object> aList = Arrays.asList("a", "b", "c");
		List<Object> bList = Arrays.asList("q", "w", "e");
		l.add(aList);//相当于map，加入之后还是一个单独集合
		l.addAll(bList);//相当于flatMap，加入之后合并到一起了
		System.out.println(l);
	}

}
